package com.zp.base.admin.security;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zp.base.admin.common.constant.BizCodeEnum;
import com.zp.base.admin.dao.RoleDao;
import com.zp.base.admin.dao.UserDao;
import com.zp.base.admin.entity.RoleEntity;
import com.zp.base.admin.entity.RoleMenuEntity;
import com.zp.base.admin.entity.UserEntity;
import com.zp.base.admin.service.RoleMenuService;
import com.zp.base.admin.service.RoleService;
import com.zp.base.admin.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 验证码校验 + 登录用户角色是否被冻结校验 + 角色是否有权限校验
 * @author zhangpeng
 */
@Component
public class ImageCodeAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private MyAuthenticationFailureHandler authenticationFailureHandler;
    @Autowired
    private UserService userService;
    @Autowired
    private RoleMenuService roleMenuService;
    @Autowired
    private RoleService roleService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        if (request.getRequestURI ().contains ("/adminLogin")) {
            try {
                String username = request.getParameter ("username");
                if (StringUtils.isEmpty (username)) {
                    throw new ImageCodeException (BizCodeEnum.USERNAME_NOT_NULL.getCode() + ":" + BizCodeEnum.USERNAME_NOT_NULL.getMsg());
                }

                String password = request.getParameter ("password");
                if (StringUtils.isEmpty (password)) {
                    throw new ImageCodeException (BizCodeEnum.PASSWORD_NOT_NULL.getCode() + ":" + BizCodeEnum.PASSWORD_NOT_NULL.getMsg());
                }
                //获取输入的验证码
                String code = request.getParameter ("captcha");
                //获取session中的验证码
                String sessionCode = (String) request.getSession ().getAttribute ("adminLogin");

                if (StringUtils.isEmpty (code)) {
                    throw new ImageCodeException (BizCodeEnum.CAPTCHA_NOT_NULL.getCode() + ":" + BizCodeEnum.CAPTCHA_NOT_NULL.getMsg());
                }

                if (!code.equalsIgnoreCase (sessionCode)) {
                    throw new ImageCodeException (BizCodeEnum.CAPTCHA_IS_ERROR.getCode() + ":" + BizCodeEnum.CAPTCHA_IS_ERROR.getMsg());
                }

                UserEntity userEntity = userService.getOne(new QueryWrapper<UserEntity>().eq("username", username));
                if (userEntity != null) {
                    //判断该用户角色是否被冻结
                    List<String> rolesByUserId = userService.findRolesByUserId(userEntity.getId());
                    if (rolesByUserId == null || rolesByUserId.size() <= 0) {
                        throw new ImageCodeException (BizCodeEnum.ROLE_IS_DISABLE.getCode() + ":" + BizCodeEnum.ROLE_IS_DISABLE.getMsg());
                    }
                    //判断已有角色下是否有权限
                    List<RoleEntity> roleEntities = roleService.list(new QueryWrapper<RoleEntity>().in("name", rolesByUserId));
                    List<Long> roleIds = roleEntities.stream().map(roleEntity -> roleEntity.getId()).collect(Collectors.toList());
                    List<RoleMenuEntity> roleMenuEntities = roleMenuService.list(new QueryWrapper<RoleMenuEntity>().in("role_id", roleIds));
                    if (roleMenuEntities == null || roleMenuEntities.size() <= 0) {
                        throw new ImageCodeException (BizCodeEnum.ROLE_HAS_NO_PERMISSIONS.getCode() + ":" + BizCodeEnum.ROLE_HAS_NO_PERMISSIONS.getMsg());
                    }

                }

            } catch (AuthenticationException e) {
                authenticationFailureHandler.onAuthenticationFailure (request, response, e);
                return;
            }
        }

        filterChain.doFilter (request, response);

    }
}
